package com.simp.service;

import java.lang.reflect.Field;

import com.baomidou.mybatisplus.annotation.TableField;
import com.simp.entity.*;
import com.simp.page.R;
import com.simp.run.EntityChildrenClassBean;
import com.simp.utils.DatabaseUtils;
import com.simp.utils.LineHumpUtils;
import com.simp.vo.ColumnVo;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author pan.shun
 * @since 2022/3/19 16:17
 */
@Service
@Slf4j
public class SourceService {

    @Value("${spring.datasource.db-name}")
    private String dbName;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private DatabaseUtils databaseUtils;

    @Autowired
    private EntityChildrenClassBean entityChildrenClassBean;

    /**
     * 查询所有表名
     */
    public R getAllTableNameList() {
        List<String> tableList = new ArrayList<>(16);
        String sql = "select table_name from information_schema.tables where table_schema='" + dbName + "' and table_type='BASE TABLE'";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
        for (Map<String, Object> m : maps) {
            for (String k : m.keySet()) {
                tableList.add(String.valueOf(m.get(k)));
            }
        }
        return R.success(tableList);
    }


    /**
     * 通过表名查询表的结构
     */
    public R getTableDetailsByName(String tableName) {

        Map<String, Object> fieldMap = new ConcurrentHashMap<>();
        // 字段与字段类型
        List<ColumnVo> fieldNameAndType = databaseUtils.getFieldNameAndType(tableName);
        // 查询字段备注
        String queryRemark = "select column_name,column_comment from information_schema.columns where table_name='" + tableName + "'";
        List<Map<String, Object>> mapList = jdbcTemplate.queryForList(queryRemark);
        Map<String, Object> m = new HashMap<>();
        mapList.forEach((r -> m.put(String.valueOf(r.get("column_name")), r.get("column_comment"))));

        fieldNameAndType.forEach(f -> {
            Object comment = m.get(f.getColumnName());
            if (!StringUtils.isEmpty(comment)) {
                f.setColumnComment(String.valueOf(comment));
            }
        });
        List<ColumnVo> entityFieldList = getEntityField(tableName);

        fieldNameAndType.sort(Comparator.comparing(ColumnVo::getColumnName));
        entityFieldList.sort(Comparator.comparing(ColumnVo::getColumnName));

        searchDifferent(fieldNameAndType, entityFieldList);

        fieldMap.put("dataBaseField", fieldNameAndType);
        fieldMap.put("entityField", entityFieldList);
        return R.success(fieldMap);
    }

    /**
     * 差异性字段标注
     */
    private void searchDifferent(List<ColumnVo> fieldNameAndType, List<ColumnVo> entityFieldList) {
        if (fieldNameAndType.size() != entityFieldList.size()) {
            Set<String> commonList = new HashSet<>();

            if (fieldNameAndType.size() > entityFieldList.size()) {
                buildCommList(commonList, entityFieldList);
            } else {
                buildCommList(commonList, fieldNameAndType);
            }
            updateStatus(commonList, fieldNameAndType);
            updateStatus(commonList, entityFieldList);
        }
    }

    private void updateStatus(Set<String> commonList, List<ColumnVo> var) {
        var.forEach(r -> {
            String columnName = r.getColumnName();
            if (columnName.contains("_")) {
                boolean flag = commonList.stream().anyMatch(f -> f.equals(columnName.toLowerCase()));
                if (!flag) {
                    r.setStatus(1);
                }
            } else {
                String aCase = LineHumpUtils.humpToLine(columnName).toLowerCase();
                boolean flag = commonList.stream().anyMatch(f -> f.equals(aCase));
                if (!flag) {
                    r.setStatus(1);
                }
            }
        });
    }

    private void buildCommList(Set<String> commonList, List<ColumnVo> var) {
        var.forEach(r -> {
            String columnName = r.getColumnName();
            if (columnName.contains("_")) {
                commonList.add(columnName.toLowerCase());
            } else {
                commonList.add(LineHumpUtils.humpToLine(columnName).toLowerCase());
            }
        });
    }

    private List<ColumnVo> getEntityField(String tableName) {
        List<ColumnVo> entityList = new ArrayList<>();
        saveClassField(entityChildrenClassBean.getEntityClass().get(tableName.toLowerCase()), entityList);
        saveClassField(CommonEntity.class, entityList);
        return entityList;
    }

    private void saveClassField(Class aClass, List<ColumnVo> entityList) {
        log.info("当前class名称 ：{}", aClass.getName());
        Field[] declaredFields = aClass.getDeclaredFields();
        if (declaredFields.length != 0) {
            for (Field f : declaredFields) {
                boolean flag;
                boolean annotationPresent = f.isAnnotationPresent(TableField.class);
                flag = !annotationPresent || f.getAnnotation(TableField.class).exist();
                if (flag) {
                    ColumnVo build = ColumnVo.builder()
                            .columnName(f.getName())
                            .columnType(f.getType().getName().substring(f.getType().getName().lastIndexOf(".") + 1))
                            .status(0)
                            .build();
                    boolean comment = f.isAnnotationPresent(ApiModelProperty.class);
                    if (comment) {
                        ApiModelProperty annotation = f.getAnnotation(ApiModelProperty.class);
                        build.setColumnComment(annotation.value());
                    }
                    entityList.add(build);
                }
            }
        }
    }


}